문자열, 리스트, 딕셔너리와 관련된 기본함수 | ✅저자: 이유정(박사)
🔹반복(iteration)의 개념과 구조
🔹 이터러블(Iterable)이란?
"하나씩 꺼낼 수 있는 값들의 모음"이에요.
즉, for문으로 반복할 수 있는 객체를 말합니다.
예: 문자열, 리스트, 튜플, 딕셔너리, range 등
🔹 이터레이터(Iterator)란?
이터러블에서 하나씩 꺼낼 수 있게 도와주는 도구입니다.
반복할 준비가 된 상태라고 보면 됩니다.
이터레이터는 한 번에 하나씩 데이터를 꺼낼 수 있는 도구예요. 그래서 한꺼번에 모든 데이터를 메모리에 올리지 않고, 필요한 만큼만 꺼내서 처리할 수 있어요.
✅ 예시 상황 1: 대용량 데이터 처리
- 예를 들어 10GB짜리 로그 파일이 있다고 해봅니다.
- 이걸 한 번에 메모리에 올리면 컴퓨터가 버틸 수 없습니다.
- 이터레이터를 쓰면 한 줄씩 읽으면서 처리할 수 있어서 메모리 부담이 적어집니다.
with open("bigfile.txt") as f:
for line in f: # 이게 이터레이터 방식
process(line)
✅ 예시 상황 2: 중간 상태 유지
- 예를 들어 데이터를 처리하다가 어디까지 했는지 기억하고 싶을 때,
- 이터레이터는 현재 위치(상태)를 내부적으로 기억하고 있어요.
- 그래서
next()
를 부르면 그다음 값부터 이어서 꺼내줘요.
nums = iter([1, 2, 3, 4, 5])
print(next(nums)) # 1
print(next(nums)) # 2
# 나중에 다시 계속 이어서
print(next(nums)) # 3
상태 기억이라는 의미는 next()
를 계속 호출하면 이어서 꺼낼수 있다는 의미의 상태 기억이지 그 위치를 밖으로 알려주거나 에러가 나서 프로그램이 종료 됐다가 다시 그상태를 이어서 실행할수는 없습니다.
이터레이터는 메모리를 아끼면서 데이터를 하나씩 순차적으로 다룰 수 있게 해주는 도구이고, 특히 데이터가 크거나, 진행 상태를 유지하면서 처리해야 하는 작업에 매우 유용합니다.
◽ 페이지 네이션 vs 이터레이터
페이지 네이션기능은 사용자 기반의 페이지 분할도구이며,
이터레이터는 서버 쪽에서 대량 데이터를 순차 처리하기 위한 도구
(메모리절약)입니다.
유튜브 영상은 한꺼번에 모든 데이터를 꺼내 놓을 수 없습니다.
인스타그램 게시물은 끝없이 업로드되기 때문에, 전체를 한 번에 불러오는 것은 비효율적입니다.
그러나 사용자가 보는 화면에는 일정 개수씩 나누어 보여주고,
필요할 때만 다음 내용을 요청합니다.
이렇게 사용자에게 데이터를 "조금씩 나눠 보여주는 UI 기능"이 페이지네이션(Pagination)이고,
서버에서는 전체 데이터를 한 번에 가져오는 대신, 필요한 만큼만 꺼내기 위해 이터레이터(iterator) 방식이 사용됩니다.
✅ 이터레이터가 주로 사용되는 5대 분야
분야 | 활용 예시 |
---|---|
1. 데이터 처리 / 분석 | 파일, 로그, CSV, 대용량 데이터 한 줄씩 처리 |
2. 웹 크롤링 / API 통신 | 페이지 수를 모를 때 yield 나 next() 로 데이터 하나씩 수집 |
3. 머신러닝 / 딥러닝 | 배치(batch) 단위로 학습 데이터를 꺼낼 때 (DataLoader , Generator ) |
4. 게임 개발 / 시뮬레이션 | 프레임 단위로 상태 업데이트 (next() 로 단계별 진행) |
5. 스트리밍 처리 | 실시간 로그, 센서 데이터, 사용자 입력 등 무한 데이터 처리 |
◽ Django에서 데이터를 가져올 때 보통 이렇게 합니다.
items = MyModel.objects.all()
이건 데이터가 수십만 개일 경우 한꺼번에 메모리에 올라가게 되어 서버가 느려지거나 멈출 수도 있어요.
그래서 Django는 대용량 데이터를 처리할 때,
이터레이터 방식으로 데이터를 "하나씩 천천히" 가져올 수 있게 도와주는 기능을 제공합니다.
</> 일반방식 (비추천 ❌ ) 그러나 개발 테스트시에는 활용할수 있음
# 게시글을 모두 불러오고 메모리에 올림 (비효율적)
posts = Post.objects.all()
for post in posts:
send_email(post.author_email, post.title)
문제점:
.all()
은 데이터를 한꺼번에 다 가져옴 → 메모리 폭발 위험
데이터가 수천~수만 개라면 서버에 부담이 큼
✅ 이터레이터 사용 방식 (추천 ✅)
# 이터레이터로 데이터를 하나씩 가져옴 (메모리 절약)
posts = Post.objects.all().iterator()
for post in posts:
send_email(post.author_email, post.title)
이점:
.iterator()
를 쓰면 DB에서 하나씩 꺼내며 처리함
메모리에 한 번에 안 올리니 서버가 안정적
큰 데이터셋에서도 빠르고 안전하게 처리 가능
✅ 실제 사용 예시 (장고 뷰에서)
from django.http import HttpResponse
from .models import Post
def notify_users(request):
count = 0
for post in Post.objects.all().iterator():
send_email(post.author_email, post.title)
count += 1
return HttpResponse(f"{count}개의 메일을 보냈습니다.")
📝 문제1] 다음 중 이터러블(iterable)객체가 아닌 것은 무엇인가요?
A. 리스트 ["a", "b", "c"]
B. 문자열 "hello"
C. 정수 123
D. 튜플 ("x", "y", "z")
✅ 정답: C
- 정수는 반복할 수 없는 객체입니다.
- 리스트, 튜플, 문자열은 모두
for
문에 넣을 수 있는 이터러블입니다.
📝 문제2] 다음 중 이터레이터(iterator)의 특징으로 올바른 설명은 무엇인가요?
A. iter()
함수는 이터레이터에서만 호출할 수 있다.
B. next()
는 리스트나 튜플에서 직접 호출할 수 있다.
C. 이터레이터는 내부적으로 현재 위치를 기억하고 next()
로 이어서 꺼낼 수 있다.
D. 이터레이터는 for
문에서 사용할 수 없다.
✅ 정답: C
- A:
iter()
는 이터러블에 호출하여 이터레이터를 생성 - B: 리스트는
next()
가 안 되고, 먼저iter()
로 변환해야 함 - D: 이터레이터도
for
문에 사용할 수 있음
📝 문제3] 다음 코드 실행 후, 두 번째 for
문에서 어떤 결과가 출력될까요?
nums = iter([10, 20, 30])
for n in nums:
print(n)
for n in nums:
print(n)
A. 10 20 30 / 10 20 30
B. 10 20 30 / (아무것도 출력되지 않음)
C. SyntaxError 발생
D. TypeError 발생
✅ 정답: B
- 이터레이터는 한 번 순회하면 끝입니다.
- 두 번째
for
문에서는 이미 다 소비된 상태이므로 출력 없음.
📝 문제4] 현재 회사 서버의 로그는 이터레이터를 사용하여 "ERROR"
메시지를 필터링하고 있습니다.
하지만 이터레이터는 한 번만 순회할 수 있어, 로그를 두 번 이상 분석해야 할 경우 재호출이 번거롭고 비효율적입니다.
아래 코드는 이터레이터 방식으로 작성된 기존 코드입니다:
logs = (
"2025-05-15 10:01:05 INFO 서버 시작됨",
"2025-05-15 10:02:14 ERROR 포트 충돌",
"2025-05-15 10:03:20 INFO 연결 성공",
"2025-05-15 10:04:01 ERROR 디스크 공간 부족",
"2025-05-15 10:05:22 INFO 종료 신호 수신"
)
log_iter = iter(logs)
print("에러 알림 로그:")
while True:
try:
line = next(log_iter)
if "ERROR" in line:
print(f"[관리자 알림] 문제 발생: {line}")
except StopIteration:
break
# 다시 순회 시도
print("\n전체 로그 다시 보기:")
for line in log_iter:
print(line) # 출력 없음 (이터레이터는 한 번만 사용 가능)
요구사항:
- 위 코드를 이터러블 방식(for문 사용)으로 바꿔서:
"ERROR"
로그만 필터링해서 출력- 전체 로그를 다시 한 번 출력
- 왜 이터러블 방식이 더 유리한지 한 문장으로 설명하세요.
✅ 정답 코드:
# 이 튜플은 여러 줄의 로그 메시지를 포함하고 있음
logs = (
"2025-05-15 10:01:05 INFO 서버 시작됨",
"2025-05-15 10:02:14 ERROR 포트 충돌",
"2025-05-15 10:03:20 INFO 연결 성공",
"2025-05-15 10:04:01 ERROR 디스크 공간 부족",
"2025-05-15 10:05:22 INFO 종료 신호 수신"
)
# 1단계: "ERROR"가 포함된 로그만 출력합니다
print("에러 알림 로그:") # 안내 메시지 출력
# 튜플 logs를 순회하면서 각 줄을 변수 line에 하나씩 꺼냅니다.
for line in logs:
# 만약 해당 줄에 "ERROR"가 포함되어 있다면,
if "ERROR" in line:
# "[관리자 알림]"이라는 메시지와 함께 해당 로그를 출력합니다.
print(f"[관리자 알림] 문제 발생: {line}")
# ✅ 2단계: 전체 로그를 다시 출력합니다.
print("\n전체 로그 다시 보기:") # 줄 바꿈 후 안내 메시지 출력
# logs를 다시 순회하여 모든 로그를 출력합니다.
# 튜플은 이터러블이기 때문에 여러 번 순회해도 문제 없습니다.
for line in logs:
print(line)
튜플은 이터러블이라서 for문을 몇 번 돌리든 항상 처음부터 다시 순회가
가능합니다. 즉, 튜플, 리스트, 딕셔너리데이터는 모두 이터리블이며
for문으로 순회할수 있는 반복 가능한 객체입니다.
반면 이터레이터는 한 번 순회하면 끝나기 때문에, 반복이 어렵습니다.
🖨️ 출력 결과:
에러 알림 로그:
[관리자 알림] 문제 발생: 2025-05-15 10:02:14 ERROR 포트 충돌
[관리자 알림] 문제 발생: 2025-05-15 10:04:01 ERROR 디스크 공간 부족
전체 로그 다시 보기:
2025-05-15 10:01:05 INFO 서버 시작됨
2025-05-15 10:02:14 ERROR 포트 충돌
2025-05-15 10:03:20 INFO 연결 성공
2025-05-15 10:04:01 ERROR 디스크 공간 부족
2025-05-15 10:05:22 INFO 종료 신호 수신
🔍 해설:
이터러블은 for
문에서 반복할 때마다 새 이터레이터를 생성하므로,
데이터를 여러 번 반복해서 순회할 수 있어 이터레이터보다 훨씬 유연하고 실용적입니다. 단, 대용량 데이터의 경우에는 메모리를 많이 차지할 수 있어 비효율적일 수 있습니다.
🔹iter()
함수란?
iter() 함수는 이터러블(iterable)한 객체(예: 리스트, 튜플, 문자열
등)를 이터레이터(iterator)로 변환해주는 내장 함수입니다.
for문에서 반복이 가능한 모든 자료형은 내부적으로 iter()가
호출됩니다. 이터레이터는 next()로 하나씩 꺼낼 수 있는 상태를 가진
객체입니다.
🔹next()
함수란?
next()는 이터레이터(iterator)에서 다음 값을 하나 꺼내서 반환해주는
내장 함수입니다. 내부적으로 이터레이터가 현재 어디까지 읽었는지
기억하고 있어서, next()를 호출할 때마다 다음 항목을 순서대로
반환합니다.
즉, 이터레이터 함수는 한번만 순회되는 구조입니다. 그래서 재사용을 할수 없습니다.
</> 예시코드: 리스트를 이터레이터로 변환해 next()
로 하나씩 꺼내기
fruits = ["사과", "바나나", "포도"]
it = iter(fruits) # 이대로 출력하면 객체원형이 됩니다.
print(next(it))
print(next(it))
print(next(it))
print(next(it)) # StopIteration 에러 → 다 꺼냄
🖨️ 출력결과:
사과
바나나
포도
Traceback (most recent call last):
File "E:\windows_v\test2.py", line 7, in <module>
print(next(it)) # StopIteration 에러 → 다 꺼냄
~~~~^^^^
StopIteration
🔍 해설:
iter(fruits)
로 리스트를 이터레이터로 변환next(it)
는 값을 하나씩 꺼내는 함수- 더 이상 꺼낼 값이 없으면
StopIteration
오류가 발생 it
은 한 번 쭉 꺼내면 끝이에요.- 다시 처음부터 꺼내고 싶으면
iter(numbers)
로 새로 만들어야 해요.
📝 문제1] 다음 코드는 next()
로 리스트의 값을 꺼내고 있습니다.
이 코드를 이터러블 방식의 for
문으로 수정하세요.
fruits = ["사과", "바나나", "포도"]
it = iter(fruits)
print(next(it))
print(next(it))
print(next(it))
✅ 정답 코드:
fruits = ["사과", "바나나", "포도"]
# for문을 사용하여 반복적으로 요소를 꺼냄
for fruit in fruits:
print(fruit)
🖨️ 출력 결과:
사과
바나나
포도
🔍 해설:
- 기존 코드는
next()
를 직접 3번 호출했기 때문에 리스트 길이만큼 정확히 써야 합니다. for
문은 내부적으로iter()
와next()
를 자동으로 사용하므로 반복 구조가 간단하고 안전합니다.- 리스트는 이터러블이므로
for
문에서 직접 사용할 수 있습니다.
🔹 with
문이란?
with는 자동으로 열고, 자동으로 닫아주는 자원 관리 문법입니다.
보통 open()처럼 파일이나 네트워크 등 “열고 닫아야 하는 자원”에
사용합니다.
📖 문법, 구문(syntax):
with 열기_함수 as 변수명:
작업문들
</>예시코드:
# 경로안에 sample.txt파일을 저장한다.
with open("sample.txt", "r", encoding="utf-8-sig") as f:
# f는 파일 객체이며, 한 줄씩 반복해서 읽을 수 있는 이터러블입니다.
for line in f:
# 각 줄을 출력하면서 끝에 붙은 줄바꿈 문자(\n)를 제거합니다.
print(line.strip())
with
는 try-finally
처럼:
- 열고(
open()
) - 사용하고(
for line in f
) - 끝나면 자동으로 닫아줍니다.
📝 문제1] 아래는 이터레이터 방식으로 텍스트 파일에서 로그를 읽고 "ERROR"
가 포함된 줄만 출력하는 코드입니다.
이 코드를 for
문으로 바꿔서 더 간결하고 안전하게 리팩터링하세요.
f = open("log.txt", "r", encoding="utf-8-sig")
log_iter = iter(f)
while True:
try:
line = next(log_iter)
if "ERROR" in line:
print("오류:", line.strip())
except StopIteration:
break
f.close()
✅ 정답 코드:
with open("log.txt", "r", encoding="utf-8-sig") as f:
for line in f:
print(line.strip())
utf-8-sig는 BOM이 포함된 UTF-8 파일을 안전하게 읽기 위해 사용하는
인코딩입니다.
BOM이 붙어 있으면 utf-8만으로는 오류가 나고, utf-8-sig로 정확히
해석할 수 있어요.
🔹 축약표현식
🔹 리스트 내포(List Comprehension)
for문을 한 줄로 요약한 축약형 표현 방식
📖 문법, 구문(syntax):
[값을_어떻게_만들지 for 변수 in 반복할_데이터]
</>예시코드:
# 일반 `for`문
words = ["Apple", "Banana", "Cat", "Django", "Zoo"]
result = [] # 결과를 담을 빈 리스트 생성
for word in words:
if len(word) >= 5: # 길이가 5 이상인 단어만
result.append(word.lower()) # 소문자로 바꿔서 리스트에 추가
print(result)
# 리스트 컴프리헨션 list comprehension
words = ["Apple", "Banana", "Cat", "Django", "Zoo"]
result = [word.lower() for word in words if len(word) >= 5]
print(result)
🖨️ 출력결과:
['apple', 'banana', 'django']
🔹 세트 내포(Set Comprehension)
리스트 컴프리헨션과 거의 동일하지만, 중복 없이 고유한 값들만 저장하
는 set(집합)을 만듭니다.
📖 문법, 구문(syntax):
{ 표현식 for 변수 in 반복가능한_객체 if 조건 }
</>예시코드:
# 일반 for문
numbers = [1, 2, 2, 3, 4, 4]
unique_squares = set() # 결과를 저장할 빈 집합 생성
for x in numbers:
square = x ** 2 # 제곱 계산
unique_squares.add(square) # 집합에 추가 (중복은 자동 제거)
print(unique_squares)
# 셋 컴프리헨션 set comprehension
numbers = [1, 2, 2, 3, 4, 4]
unique_squares = {x**2 for x in numbers}
print(unique_squares)
🖨️ 출력결과:
{16, 1, 4, 9}
🔹 딕셔너리 내포(Dictionary Comprehension)
반복 가능한 객체를 기반으로 key: value 쌍을 생성해서 딕셔너리를
만드는 표현입니다.
📖 문법, 구문(syntax):
{ 키_표현식: 값_표현식 for 변수 in 반복가능한_객체 if 조건 }
</>예시코드:
# 일반 for문
words = ["apple", "banana", "cherry"]
word_lengths = {} # 빈 딕셔너리 생성
for word in words:
word_lengths[word] = len(word) # 키: 단어, 값: 단어 길이
print(word_lengths)
# 딕셔너리 컴프리헨션 dictionary comprehension
words = ["apple", "banana", "cherry"]
word_lengths = {word: len(word) for word in words}
print(word_lengths)
🖨️ 출력결과:
{'apple': 5, 'banana': 6, 'cherry': 6}
🔹 제너레이터 표현식(Generator Expression)
리스트 컴프리헨션과 매우 비슷하지만, 리스트처럼 전체를 메모리에
올리지 않고 필요할 때 하나씩 꺼내 쓰는 이터레이터를 만듭니다.
📖 문법, 구문(syntax):
( 표현식 for 변수 in 반복가능한_객체 if 조건 )
</>예시코드:
# 일반for문 next()처럼 하나씩 꺼내기
squares = [] # 리스트에 미리 값을 저장
for x in range(5):
squares.append(x ** 2)
# next처럼 하나씩 꺼내 출력
print(squares[0]) # 0
print(squares[1]) # 1
print(squares[2]) # 4
# 제너레이터 표현식
squares = (x**2 for x in range(5))
print(next(squares)) # 0
print(next(squares)) # 1
print(next(squares)) # 4
✔️ next()
로 하나씩 꺼낼 수 있음. 메모리 절약에 유리!
📝 문제1] 다음 리스트에서 중복을 제거하고, 각 숫자를 제곱한 결과를 세트로 만들어 출력하세요.
단, 짝수만 제곱합니다. (세트 내포 - 중복 제거 응용)
nums = [2, 3, 4, 4, 5, 6, 6, 7]
🖨️ 출력 결과:
{16, 36, 4}
✅ 정답 코드:
nums = [2, 3, 4, 4, 5, 6, 6, 7]
unique_even_squares = {x**2 for x in nums if x % 2 == 0}
print(unique_even_squares)
🔍 해설:
- 세트 내포는 중복을 자동 제거합니다.
x % 2 == 0
조건을 통해 짝수만 필터링합니다.
📝 문제2] 다음 문자열 리스트에서 길이가 4자 이상인 단어들의 첫 글자만 뽑아서 중복 없이 출력하세요. (세트 내포 - 문자열 조건 필터링)
words = ["data", "dev", "AI", "api", "node", "java", "go"]
🖨️ 출력 결과:
{'a', 'd', 'g'}
✅ 정답 코드:
words = ["data", "dev", "AI", "api", "node", "java", "go"]
short_first_letters = {word[0] for word in words if len(word) => 4}
print(short_first_letters)
🔍 해설:
- 각 단어의
word[0]
은 첫 글자입니다. - 길이 조건을 만족하는 단어만 대상으로 세트 생성.
📝 문제3] 다음 사용자 목록에서 이름을 키로, 나이를 값으로 갖는 딕셔너리를 만드세요. 단, 나이가 30세 이상인 사용자만 포함합니다. (딕셔너리 내포 - 값 가공)
users = [
{"name": "Alice", "age": 25},
{"name": "Bob", "age": 35},
{"name": "Charlie", "age": 40}
]
🖨️ 출력 결과:
{'Bob': 35, 'Charlie': 40}
✅ 정답 코드:
users = [
{"name": "Alice", "age": 25},
{"name": "Bob", "age": 35},
{"name": "Charlie", "age": 40}
]
age_filtered = {user["name"]: user["age"] for user in users if user["age"] >= 30}
print(age_filtered)
🔍 해설:
user["name"]: user["age"]
로 딕셔너리 구성- 조건 필터링으로 나이 30 이상만 포함
📝 문제4] HTTP 헤더 정보를 담은 리스트에서, 각 항목을 딕셔너리로 변환하세요. 키는 소문자로, 값은 문자열로 유지합니다. (딕셔너리 내포 - 데이터 포맷 변환)
headers = [
("Host", "example.com"),
("Authorization", "Bearer xyz"),
("Content-Type", "application/json")
]
🖨️ 출력 결과:
{'host': 'example.com', 'authorization': 'Bearer xyz', 'content-type': 'application/json'}
✅ 정답 코드:
headers = [("Content-Type", "application/json"), ("Authorization", "Bearer xyz")]
header_dict = {k.lower(): v for k, v in headers}
print(header_dict)
🔍 해설:
(k, v)
튜플을 순회하며k.lower()
로 키 소문자화- 실무에서 HTTP header 처리할 때 유용한 패턴
📝 문제5] 1부터 1,000,000까지의 정수 중에서 3의 배수의 합을 구하되,
리스트를 만들지 않고 제너레이터 표현식을 사용해 처리하세요.
(제너레이터 표현식 - 메모리 절약)
sum()
함수는 숫자들의 합을 계산하는데 사용됩니다.
sum(iterable, start=0)
🖨️ 출력 결과:
166,666,833,333
✅ 정답 코드:
total = sum(x for x in range(1_000_001) if x % 3 == 0)
print(f"{total:,}")
🔍 해설:
x for x in ...
은 리스트를 만들지 않고 하나씩 순회함 (제너레이터)sum()
과 함께 쓰면 메모리 효율적인 집계 가능
💡 리스트 내포는 코드의 가독성을 높이고,
리스트 생성 작업을 매우 간단하게 처리할 수 있는 파이썬의 강력한 문법입니다. 특히 데이터 가공, 필터링, 변환 작업에 자주 활용돼요.
🔹 여러 줄 문자열 작성 시 주의점
파이썬은 여러 줄의 문자열을 나열할 때 문법 오류가 발생하기 쉬워요.
특히 list, print(), return 구문 안에 긴 문자열을 여러 줄에 나눠
쓸 경우 연결이 되지 않거나 줄바꿈이 생겨서 원하는 출력이 안될 수 있음
❌ 잘못된 코드 1: list
안에 긴 문자열을 줄바꿈해서 쓴 경우
my_list = ["이 문자열은 너무 길어서
다음 줄에 나눠 작성했어요."]
print(my_list)
🛑 오류 발생:
SyntaxError: unterminated string literal
🔍 이유:
- 리스트 내부에서
"문자열"
을 줄바꿈해서 쓰면 파이썬은 문자열이 끝났는지 모르기 때문에 문법 오류 발생
❌ 잘못된 코드 2: return
구문에서 줄바꿈된 문자열
def get_message():
return "이 문장은 너무 길어서
두 줄로 나눴어요."
🛑 오류 발생:
SyntaxError: unterminated string literal
🔍 이유:
return
구문에서도 문자열이 줄바꿈되면 문자열이 닫히지 않은 채 끝났다고 판단함
⭕ 해결 방법 1: join()
사용
lines = ["이 문자열은", "join 함수로", "합쳤어요"]
message = " ".join(lines)
print(message)
⭕ 해결 방법 2: 여러 줄 문자열 """ """
사용 (출력에 줄바꿈 포함됨)
def get_message():
return """이 문장은 너무 길어서
두 줄로 나눠졌어요."""
◽ 대표적인 iterable 자료형
자료형 | 예시 | 설명 |
---|---|---|
리스트 | [1, 2, 3] |
값들을 하나씩 순서대로 꺼낼 수 있음 |
튜플 | (10, 20, 30) |
리스트와 비슷하지만 수정 불가 |
문자열 | "hello" |
문자 하나하나도 꺼낼 수 있음 |
딕셔너리 | {"a": 1, "b": 2} |
기본적으로 키를 반복함 |
집합(set) | {1, 2, 3} |
순서는 없지만 꺼내는 건 가능 |
range() |
range(5) |
0부터 4까지 숫자를 생성함 |
-
튜플, 리스트는 모두 이터러블입니다.
- 여러 개의 값을 담고 있고,
- 그 값을 하나씩 꺼내서 사용할 수 있기 때문입니다.
-
for
문,*
전개 연산자,in
조건문에서 사용할 수 있어요.
🔹 내장함수
파이썬이 기본적으로 준비해 둔, 바로 쓸 수 있는 함수들입니다.
내장함수(built-in function)는 “함수 호출”을 통해 직접 사용할 수
있는 도구입니다.
함수 이름을 쓰고, 괄호 () 안에 필요한 값을 넣는 것을 함수 호출이라고
합니다.
📘 수학/숫자 관련 함수
함수 | 설명 |
---|---|
abs(x) |
숫자의 절댓값을 반환합니다 |
round(x,n) |
소수점 이하 n 자리까지 반올림합니다 |
max(iterable) |
최대값 반환합니다 |
min(iterable) |
최솟값 반환합니다 |
sum(iterable) |
합계를 계산합니다 |
pow(x, y) |
x 의 y 제곱을 계산합니다 |
divmod(x, y) |
x 를 y 로 나눈 몫과 나머지를 튜플로 반환합니다 |
예시 |
---|
abs(-10) → 10 |
round(3.14159, 2) → 3.14 |
max(3, 10, 7) → 10 |
min(3, 10, 7) → 3 |
sum([1, 2, 3]) → 6 |
pow(2, 3) → 8 |
divmod(7, 3) → (2, 1) |
</> 예시코드: |
print(abs(-10)) # 10
print(round(3.1415, 2)) # 3.14
print(max(1, 5, 3)) # 5
print(min(1, 5, 3)) # 1
print(sum([4, 5, 6])) # 15
print(pow(2, 4)) # 16
print(divmod(10, 3)) # (3, 1)
🔹 리스트에 적용되는 기본 함수: min( ), max( ), sum( )
파이썬에서는 숫자 리스트에 대해 최솟값, 최댓값, 합계를 쉽게 구할
수 있는 기본 내장 함수를 제공해요.
함수 | 설명 |
---|---|
min() |
리스트에서 가장 작은 값 반환 |
max() |
리스트에서 가장 큰 값 반환 |
sum() |
리스트에 있는 모든 값의 합 계산 |
📖 문법, 구문(syntax): |
max(iterable, key=기준함수)
min(iterable, key=기준함수)
sum(iterable, start=0)
</> 예시코드: 제품별 월간 매출에서 최다 판매 상품, 최저 판매 상품, 총합 매출 구하기
# 각 상품별 3월 매출 데이터 (단위: 원)
products = [
{"name": "에어컨", "sales": 3200000},
{"name": "선풍기", "sales": 850000},
{"name": "노트북", "sales": 2150000},
{"name": "세탁기", "sales": 2750000},
{"name": "청소기", "sales": 650000}
]
# 최다 판매 상품 일반함수
def top_product(item):
return item["sales"]
top_product = max(products, key=top_product)
print(top_product)
# 최다 판매 상품 람다함수
top_product = max(products, key=lambda item: item["sales"])
# ----------------------------------------
# 최저 판매 상품 일반함수
def low_product(item):
return item["sales"]
low_product = min(products, key=low_product)
print(low_product)
# 최저 판매 상품 람다함수
low_product = min(products, key=lambda item: item["sales"])
# ----------------------------------------
# 전체 상품 매출 합계 일반 for문
total_sales = 0
for item in products:
total_sales += item["sales"]
print(total_sales)
# 전체 상품 매출 합계 제너레이터 표현식 ( 표현식 for 변수 in 반복가능한_객체 if 조건 )
total_sales = sum(item["sales"] for item in products)
# ----------------------------------------
print("최다 판매 상품:", top_product["name"], "-", top_product["sales"], "원")
print("최저 판매 상품:", low_product["name"], "-", low_product["sales"], "원")
print("전체 매출 합계:", total_sales, "원")
🖨️ 출력결과:
최다 판매 상품: 에어컨 - 3200000 원
최저 판매 상품: 청소기 - 650000 원
전체 매출 합계: 9600000 원
🔍 해설:
max(리스트, key=람다식)
→ 각 딕셔너리에서"sales"
값 기준으로 최댓값을 가진 항목을 반환min(리스트, key=람다식)
→"sales"
값 기준으로 최솟값을 가진 항목을 반환sum(표현식 for item in 리스트)
→ 모든 상품의"sales"
값을 누적합산
📝 문제1] 매출 데이터에서 요약 통계 구하기
다음은 한 주간의 일별 매출 기록입니다.
매출 데이터를 기반으로 최고 매출일, 최저 매출일, 총 매출을 구하세요.
sales = {
"Mon": 120000,
"Tue": 90000,
"Wed": 150000,
"Thu": 70000,
"Fri": 110000
}
🖨️ 출력 결과:
최고 매출일: Wed - 150,000원
최저 매출일: Thu - 70,000원
총 매출: 540,000원
✅ 정답 코드:
sales = {
"Mon": 120000,
"Tue": 90000,
"Wed": 150000,
"Thu": 70000,
"Fri": 110000
}
# 최댓값(가장 많이 번 날)과 최솟값(가장 적게 번 날)
max_day = max(sales, key=sales.get) # 매출이 가장 높은 요일
min_day = min(sales, key=sales.get) # 매출이 가장 낮은 요일
total_sales = sum(sales.values()) # 총 매출
print("최고 매출일:", {max_day: ,} - {sales[max_day]: ,} , "원")
print("최저 매출일:", min_day, "-", sales[min_day], "원")
print("총 매출:", total_sales, "원")
🔍 해설:
max(sales, key=sales.get)
: 딕셔너리에서 값(매출)이 가장 큰 키(요일)를 반환min(...)
: 가장 낮은 매출을 가진 요일을 찾음sum(sales.values())
: 딕셔너리의 값만 합산해서 총합을 구함
📝 문제2] 다음은 한 회사의 상품별 3월 매출 데이터입니다.
이 데이터를 활용하여 아래 물음에 답하세요. (월간 매출 분석)
sales = {
"키보드": 125000,
"모니터": 345000,
"마우스": 85000,
"노트북": 890000,
"스피커": 142000
}
문제:
- 매출이 가장 높은 제품과 그 금액은?
- 매출이 가장 낮은 제품과 그 금액은?
🖨️ 출력 결과:
최고 매출: 노트북 - 890000 원
최저 매출: 마우스 - 85000 원
총 매출: 1587000 원
✅ 정답 코드:
sales = {
"키보드": 125000,
"모니터": 345000,
"마우스": 85000,
"노트북": 890000,
"스피커": 142000
}
max_item = max(sales, key=sales.get)
min_item = min(sales, key=sales.get)
total = sum(sales.values())
print(f"최고 매출: {max_item} - {sales[max_item]} 원")
print(f"최저 매출: {min_item} - {sales[min_item]} 원")
print(f"총 매출: {total} 원")
🔍 해설:
- 리스트의 모든 숫자를 더한 값 →
4 + 8 + 2 + 6 = 20
sum()
함수는 리스트에 있는 값들을 자동으로 합산해줘요
📝 문제3] 다음은 각 직원의 1분기 실적(건수)입니다.
성과 데이터를 활용하여 아래를 구하세요. (직원 성과 평가)
performance = {
"Alice": 23,
"Bob": 15,
"Charlie": 31,
"Diana": 18,
"Ethan": 26
}
문제:
- 가장 많은 실적을 낸 직원과 그 건수는?
- 실적이 가장 낮은 직원은?
- 평균 실적은 얼마인가? (소수점은 반올림하지 않고 표시)
🖨️ 출력 예시:
최다 실적자: Charlie - 31건
최저 실적자: Bob - 15건
평균 실적: 22.6건
✅ 정답 코드:
performance = {
"Alice": 23,
"Bob": 15,
"Charlie": 31,
"Diana": 18,
"Ethan": 26
}
max_emp = max(performance, key=performance.get)
min_emp = min(performance, key=performance.get)
average = sum(performance.values()) / len(performance)
print(f"최다 실적자: {max_emp} - {performance[max_emp]}건")
print(f"최저 실적자: {min_emp} - {performance[min_emp]}건")
print(f"평균 실적: {average}건")
🔍 해설:
max(performance, key=performance.get)
: 실적이 가장 높은 직원 반환min(...)
: 실적이 가장 낮은 직원 반환sum(...) / len(...)
: 전체 실적 평균 계산 (소수 포함)
📘 형변환 함수 (타입 변경)
함수 | 설명 | 예시 |
---|---|---|
int() |
정수로 변환 | int("5") → 5 |
float() |
실수로 변환 | float("3.14") → 3.14 |
str() |
문자열로 변환 | str(123) → "123" |
bool() |
논리값으로 변환 | bool(0) → False |
list() |
리스트로 변환 | list("abc") → ['a', 'b', 'c'] |
tuple() |
튜플로 변환 | tuple([1, 2]) → (1, 2) |
set() |
집합으로 변환 | set("hello") → {'h', 'e', 'l', 'o'} |
dict() |
딕셔너리로 변환 | dict([(1, 'a'), (2, 'b')]) → {1: 'a', 2: 'b'} |
</> 예시코드:
print(int("10")) # 10
print(float("3.5")) # 3.5
print(str(100)) # '100'
print(bool("")) # False
print(list("hi")) # ['h', 'i']
print(tuple([3, 4])) # (3, 4)
print(set("aabb")) # {'a', 'b'}
print(dict([(1, 'one'), (2, 'two')])) # {1: 'one', 2: 'two'}
📘 반복/자료형 함수
함수 | 설명 |
---|---|
len(x) |
길이 반환. 문자열, 리스트, 튜플 등에 사용 가능 |
range(start, stop, step) |
숫자 범위 생성 |
enumerate(x) |
인덱스와 값을 함께 반환 |
zip(a, b) |
두 시퀀스를 병렬 처리. 튜플 쌍 반환 |
reversed(x) |
역순 객체 반환 |
sorted(x) |
정렬된 리스트 반환 (원본은 유지됨) |
dict.items() |
딕셔너리의 (key, value) 쌍을 튜플 형태로 반환. 반복문에서 자주 사용됨 |
예시 |
---|
len("hello") → 5 |
range(1, 5) → [1, 2, 3, 4] |
enumerate(['a', 'b']) |
zip([1,2],[3,4]) |
reversed([1,2,3]) |
sorted([3, 1, 2]) → [1, 2, 3] |
list({'a':1, 'b':2}.items()) → [('a', 1), ('b', 2)] |
🔹 enumerate( ) 함수와 반복문 조합하기
enumerate() 함수는 반복 가능한 객체(리스트, 문자열 등)를 순회할 때
각 요소와 함께 인덱스(번호)도 함께 가져올 수 있게 해주는 함수예요.
일반적인 for문에서는 인덱스를 따로 관리해야 하지만,
enumerate()를 사용하면 자동으로 번호와 값을 동시에 다룰 수 있어요.
📖 문법, 구문(syntax):
enumerate(iterable, start=0)
</> 예시코드: 리스트를 enumerate()
로 인덱스와 함께 출력하기
fruits = ["사과", "바나나", "포도"]
for i, fruit in enumerate(fruits):
print(i, fruit)
🖨️ 출력결과:
0 사과
1 바나나
2 포도
🔍 해설:
enumerate(fruits)
는 (0, "사과"), (1, "바나나") ... 형태의 튜플을 반환i
는 인덱스(순번),fruit
은 리스트 요소- 순서와 데이터를 동시에 다루고 싶을 때 매우 유용
</> 예시코드: 서버 로그 항목에 번호를 붙여 중요 에러 표시
# 서버에서 수집된 로그 목록
logs = [
"INFO: 시스템 정상 작동",
"ERROR: 사용자 인증 실패",
"WARNING: 디스크 공간 부족",
"ERROR: 데이터베이스 연결 실패",
"INFO: 백업 완료"
]
# 로그 항목마다 번호를 붙이며 에러 로그는 ★ 표시
for i, log in enumerate(logs, start=1):
marker = "★" if "ERROR" in log else " " # 에러 로그 강조
print(f"{i:02d}. {marker} {log}")
🖨️ 출력 결과:
1. INFO: 시스템 정상 작동
2. ★ ERROR: 사용자 인증 실패
3. WARNING: 디스크 공간 부족
4. ★ ERROR: 데이터베이스 연결 실패
5. INFO: 백업 완료
🔍 해설:
enumerate(logs, start=1)
로그에 1번부터 번호 매김i:02d
번호를 항상 2자리로 출력 (01
,02
, ...)"★" if "ERROR" in log else " "
에러 로그는 눈에 띄게 표시
🔹zip 함수의 기본 개념
두 리스트를 인덱스 기준으로 묶어서
(1, 3), (2, 4) 이런 식의 쌍(pair)으로 만들어주는 함수예요.
📖 문법, 구문(syntax):
zip(iterable1, iterable2, ..., iterableN)
</> 예시코드: 리스트를 enumerate()
로 인덱스와 함께 출력하기
z = zip([1, 2], [3, 4])
print(list(z))
# -----------------
names = ["영희", "철수"]
ages = [22, 25]
for name, age in zip(names, ages):
print(f"{name}의 나이는 {age}세입니다.")
🖨️ 출력결과:
[(1, 3), (2, 4)]
영희의 나이는 22세입니다.
📝 문제1] 다음 로그 리스트를 enumerate()
를 사용해 번호와 함께 출력하되,
"ERROR"
가 포함된 항목 앞에는 [!ERROR]
표시를 붙여 강조하세요.
번호는 1부터 시작합니다.
logs = [
"INFO 서버 시작",
"ERROR 인증 실패",
"WARNING 디스크 부족",
"ERROR 연결 오류",
"INFO 백업 완료"
]
🖨️ 출력 결과:
1. INFO 서버 시작
2. [!ERROR] ERROR 인증 실패
3. WARNING 디스크 부족
4. [!ERROR] ERROR 연결 오류
5. INFO 백업 완료
✅ 정답 코드:
logs = [
"INFO 서버 시작",
"ERROR 인증 실패",
"WARNING 디스크 부족",
"ERROR 연결 오류",
"INFO 백업 완료"
]
for i, log in enumerate(logs, start=1):
tag = "[!ERROR]" if "ERROR" in log else " "
print(f"{i:02d}. {tag} {log}")
🔍 해설:
enumerate(..., start=1)
로 번호를 1번부터 출력i:02d
는 번호를 항상 2자리로 출력 (01
,02
, ...)"ERROR"
포함 여부에 따라[!ERROR]
표시
📝 문제2] 사용자 점수 등급 출력 아래의 사용자 점수 리스트를 사용하여, 각 사용자에 대해 번호, 이름, 점수, 등급을 출력하세요.
- 점수가 90 이상: A
- 80 이상: B
- 나머지: C
users = [("민수", 92), ("영희", 81), ("철수", 75)]
🖨️ 출력 결과:
1. 이름: 민수, 점수: 92, 등급: A
2. 이름: 영희, 점수: 81, 등급: B
3. 이름: 철수, 점수: 75, 등급: C
✅ 정답 코드:
users = [("민수", 92), ("영희", 81), ("철수", 75)]
for i, (name, score) in enumerate(users, start=1):
if score >= 90:
grade = "A"
elif score >= 80:
grade = "B"
else:
grade = "C"
print(f"{i}. 이름: {name}, 점수: {score}, 등급: {grade}")
🔍 해설:
enumerate(..., start=1)
→ 번호 부여for i, (name, score)
→ 튜플의 요소를 동시에 언패킹- 조건문을 활용한 실시간 등급 분류 처리
📝 문제3] 사용자가 입력한 문장 줄 번호 붙여 출력하기
사용자로부터 여러 줄의 문장을 입력받아 리스트에 저장한 후,
줄 번호를 붙여 출력하세요.
입력은 3줄로 제한하며, 줄 번호는 1부터 시작합니다.
🖨️ 출력 예시:
3줄의 문장을 입력하세요:
> 첫눈이 왔다
> 창밖이 하얗다
> 커피가 생각났다
입력한 문장:
1: 첫눈이 왔다
2: 창밖이 하얗다
3: 커피가 생각났다
✅ 정답 코드:
lines = []
print("3줄의 문장을 입력하세요:")
for _ in range(3):
line = input("> ")
lines.append(line)
print("\n 입력한 문장:")
for i, line in enumerate(lines, start=1):
print(f"{i}: {line}")
🔍 해설:
enumerate(..., start=1)
로 번호 붙이기- 입력을 리스트에 저장한 뒤 출력 시 순서 매김
- 실무에서 사용자 입력 기록, 에디터 기능, 파일 줄 표시 등에 활용 가능
🔹 reversed( ) 함수로 리스트 뒤집기
reversed() 함수는 리스트나 문자열 같은 순서가 있는 자료형(시퀀스)을
뒤에서부터 거꾸로 순회(iteration)할 수 있게 해주는 내장 함수예요.
즉, 리스트나 문자열을 거꾸로 하나씩 꺼낼 수 있게 도와주는 파이썬 도구
입니다.
⚠️ 하지만! 주의할 점이 있어요: 원래 리스트는 그대로 유지되고, 거꾸로 꺼내볼 수 있는 도구(반복자)를 만들어줍니다.
📖 문법, 구문(syntax):
reversed(iterable)
</> 예시코드: 최신 알림 로그를 최근 순으로 출력하기
# 시간순으로 저장된 시스템 알림 로그 (오래된 것 → 최신순)
notifications = [
"[08:12] 서버 시작됨",
"[09:05] 사용자 로그인",
"[09:47] 오류 발생: DB 연결 실패",
"[10:02] 자동 백업 완료",
"[10:45] 관리자 로그아웃"
]
# 가장 최근 알림이 먼저 보이도록 역순으로 출력
print("최신 알림 내역 (최근순):")
for idx, notice in enumerate(reversed(notifications), start=1):
print(f"{idx}. {notice}")
🖨️ 출력결과:
최신 알림 내역 (최근순):
1. [10:45] 관리자 로그아웃
2. [10:02] 자동 백업 완료
3. [09:47] 오류 발생: DB 연결 실패
4. [09:05] 사용자 로그인
5. [08:12] 서버 시작됨
◽ 리스트로 저장하고 가공하고 싶을 때
# 알림 로그: 시간순으로 저장됨 (오래된 → 최신)
notifications = [
"[08:12] 서버 시작됨",
"[09:05] 사용자 로그인",
"[09:47] 오류 발생: DB 연결 실패",
"[10:02] 자동 백업 완료",
"[10:45] 관리자 로그아웃"
]
# reversed()를 사용해 역순으로 만들고, list()로 리스트로 저장
recent_logs = list(reversed(notifications))
# 최근 2개 알림 추출 (슬라이싱)
latest_two = recent_logs[:2]
# 출력
print("최근 알림 2개:")
for i, log in enumerate(latest_two, start=1):
print(f"{i}. {log}")
🖨️ 출력결과:
최근 알림 2개:
1. [10:45] 관리자 로그아웃
2. [10:02] 자동 백업 완료
🔍 해설:
reversed(notifications)
알림을 뒤집음 (최신 → 오래된 순)list(...)
이터레이터를 리스트로 변환하여 인덱싱 가능[:2]
최근 2개의 항목 추출enumerate(..., start=1)
번호를 1부터 붙여 출력
◽ reversed()
vs sort().reverse()
차이점
reversed()
는 그냥 순서만 뒤집어 보여주는 도구이고,
.sort().reverse()
는 정렬된 순서를 직접 바꾸는 작업
</> 예시코드: reversed()
사용
# 시간순으로 기록된 상품 가격 변화 (오래된 → 최신)
price_log = [10000, 12000, 11500, 13000]
# 최근 가격부터 보기 (순서만 뒤집음, 원본은 그대로 유지)
for i, price in enumerate(reversed(price_log), start=1):
print(f"{i}일 전 가격: {price}원")
print("원본 가격 로그:", price_log)
🖨️ 출력 결과:
1일 전 가격: 13000원
2일 전 가격: 11500원
3일 전 가격: 12000원
4일 전 가격: 10000원
원본 가격 로그: [10000, 12000, 11500, 13000]
🔍 해설:
reversed(price_log)
는 원본을 수정하지 않고 거꾸로 보는 뷰(iterator)를 제공합니다.- 로그 데이터, 시계열 데이터, 거래 내역 등 기록 순서를 유지한 채로 최근부터 순회할 때 사용됩니다.
</> 예시코드:
sort()
+ reverse()
사용 – 가격 순으로 정렬 후 내림차순 보고
# 상품별 가격 목록 (정렬이 필요함)
product_prices = [42000, 39000, 50000, 32000]
# 가장 비싼 상품부터 보기 (내림차순 정렬)
product_prices.sort() # 오름차순 정렬
product_prices.reverse() # 뒤집어서 내림차순
print("가격순 정렬 결과 (내림차순):")
for i, price in enumerate(product_prices, start=1):
print(f"{i}. {price}원")
🖨️ 출력 결과:
가격순 정렬 결과 (내림차순):
1. 50000원
2. 42000원
3. 39000원
4. 32000원
🔍 해설:
.sort()
→ 정렬 (기본은 오름차순).reverse()
→ 정렬된 결과를 뒤집어 *림차순- 원본 리스트
product_prices
는 이 과정을 거치며 영구히 변경됩니다.
📝 문제1] 최근 로그를 최신순으로 출력하기
다음은 시스템 로그가 저장된 리스트입니다.
이 로그를 reversed()
를 사용하여 최신 로그부터 출력하세요.
출력 형식은 "n번 로그: 메시지"이며, n은 1부터 시작합니다.
logs = [
"08:01 시스템 시작",
"08:45 사용자 로그인",
"09:10 데이터 저장",
"10:30 시스템 종료"
]
🖨️ 출력 예시:
최신 로그:
1번 로그: 10:30 시스템 종료
2번 로그: 09:10 데이터 저장
3번 로그: 08:45 사용자 로그인
4번 로그: 08:01 시스템 시작
✅ 정답 코드:
logs = [
"08:01 시스템 시작",
"08:45 사용자 로그인",
"09:10 데이터 저장",
"10:30 시스템 종료"
]
print("최신 로그:")
for i, log in enumerate(reversed(logs), start=1):
print(f"{i}번 로그: {log}")
🔍 해설:
reversed(logs)
→ 리스트 순서를 거꾸로 보기 (최근 로그부터)enumerate(..., start=1)
→ 번호 매기기- 실무에서 알림, 에러 로그, 기록 리스트 최신순 표시에 매우 유용
📝 문제2] 사용자 최근 입력값 3개를 거꾸로 출력하기
사용자에게 입력을 5번 받아 리스트에 저장하고,
가장 최근 입력 3개만 거꾸로 출력하세요.
🖨️ 출력 결과:
단어 입력: apple
단어 입력: banana
단어 입력: cherry
단어 입력: date
단어 입력: egg
최근 입력 3개:
1. egg
2. date
3. cherry
✅ 정답 코드:
inputs = []
# 사용자 입력 5회 받기
for _ in range(5):
word = input("단어 입력: ")
inputs.append(word)
# 최근 입력 3개만 추출 → 역순으로 출력
print("\n 최근 입력 3개:")
for i, word in enumerate(reversed(inputs[-3:]), start=1):
print(f"{i}. {word}")
🔍 해설:
inputs[-3:]
→ 최근 3개 슬라이싱reversed(...)
→ 거꾸로 출력 (최신순)- 실무에서 사용자 이력, 검색 기록, 최근 알림 등의 처리 방식과 유사
📝 문제3] 날짜별 매출 데이터를 역순으로 출력하기
다음은 날짜별 매출 기록입니다.
최근 날짜부터 매출을 출력하되, 출력은 "날짜 - 금액원"
형식으로 작성하세요.
sales = [
("2024-01-01", 150000),
("2024-01-02", 178000),
("2024-01-03", 162500)
]
🖨️ 출력 예시:
최근 매출 내역:
2024-01-03 - 162500원
2024-01-02 - 178000원
2024-01-01 - 150000원
✅ 정답 코드:
sales = [
("2024-01-01", 150000),
("2024-01-02", 178000),
("2024-01-03", 162500)
]
print("최근 매출 내역:")
for date, amount in reversed(sales):
print(f"{date} - {amount}원")
🔍 해설:
- 튜플 목록을
reversed()
로 순회 - 언패킹하여 날짜, 금액으로 출력
- 실무에서 정렬 없이 입력 순서 유지 + 최신순 출력 시 많이 사용
📘 타입 확인 및 특수 기능 함수
함수 | 설명 |
---|---|
type(x) |
자료형 확인 |
id(x) |
객체의 고유 식별자 반환 |
isinstance(x, T) |
x 가 타입 T (자료형타입)의 인스턴스인지 확인 |
callable(x) |
호출 가능한 객체인지 확인 (함수인지 등) |
eval(str) |
문자열 코드를 실행하고 결과 반환 |
exec(str) |
문자열 코드 실행 (결과 반환 없음) |
예시 |
---|
type("hi") → <class 'str'> |
id(5) |
isinstance(5, int) → True |
callable(print) → True |
eval("2+3") → 5 |
exec("x=5") 후 print(x) |
</> 예시코드:
print(type([1,2])) # <class 'list'>
print(id(100)) # 객체 고유값 (숫자 다름)
print(isinstance("hi", str)) # True
print(callable(len)) # True
print(eval("3 * 4")) # 12
exec("a = 10") # 실행됨
print(a) # 10
🔹 id()
함수: 중요도는 높지 않으나 이해 차원에서 정리한 내장함수입니다.
변수나 객체의 "고유 주소값(ID)"을 반환합니다.
메모리상의 위치처럼, 값은 같아도 id는 다를 수 있음.
🧾쉽게말하면:
파이썬이 어떤 값을 저장할 때, 메모리에 올려놓는 위치(주소)가 있어요.
id()
는 이 주소를 숫자 형태로 보여주는 함수입니다.
그러나 숫자처럼 변하지 않는 값을 불변객체라고 하며 메모리 재사용(최적화)를 위해 이렇게 주소의 위치를 지정합니다.
🧐 id함수는 언제 사용되나? 참조확인: 같은 객체인지 확인 불변 객체 최적화 확인: 정수, 문자열 등의 공유 여부 파악 디버깅: 함수 안팎에서 객체가 바뀌었는지 추적
</> 예시코드:
a = 10
b = 10
c = 20
print("a의 id:", id(a))
print("b의 id:", id(b))
print("c의 id:", id(c))
🖨️ 출력결과: 컴퓨터마다 다름
a의 id: 140706765241328
b의 id: 140706765241328
c의 id: 140706765241648
🔍 해설:
a
와b
는 값도 같고 같은 객체로 인식되어 같은 ID를 가짐.c
는 값이 다르기 때문에 ID도 다름.
🔹 isinstance(x, T)
함수
x
가 T 자료형인지 확인합니다.
결과는 True
또는 False
로 반환됩니다.
</> 예시코드:
x = 123
y = "hello"
z = [1, 2, 3]
print(isinstance(x, int)) # True
print(isinstance(y, str)) # True
print(isinstance(z, list)) # True
print(isinstance(y, int)) # False
🖨️ 출력결과: 컴퓨터마다 다름
True
True
True
False
🔍 해설:
x
는int
,y
는str
,z
는list
이기 때문에 각각의 타입 확인이 가능.y
는 문자열이므로int
인지 묻는 건False
.
🔹 exec(str)
함수
문자열 형태로 된 파이썬 코드를 실행합니다.
eval()
은 결과를 반환하지만, exec()
는 결과 없이 실행만 합니다.
</> 예시코드:
code = """
x = 5
y = 10
z = x + y
print("계산 결과:", z)
"""
exec(code) # 문자열 코드 실행
🖨️ 출력결과: 컴퓨터마다 다름
계산 결과: 15
🔍 해설:
exec()
는code
문자열을 마치 코드처럼 실행함.- 변수 선언도 가능하고, 출력도 할 수 있음.
- 주로 동적으로 코드를 만들거나 실행할 때 사용됨.
🔹 eval()
함수
문자열을 파이썬 코드를 실제로 실행하는 함수입니다.
간단한 계산기 만들기나 동적으로 코드 실행하기 및 작은 언어(DSL)를 구현할때 사용합니다. 그러나 문자열이 무엇이든 실행하기 때문에 외부에서 입력한 값이 위험한 코드일 경우에는 그냥 실행해버립니다.
그래서 보안에 취약하기 때문에 실제 서비스에는 거의 사용하지 않습니다.
꼭 써야 한다면 믿을수 있는 내부 코드에서만 사용합니다.
📖 문법, 구문(syntax):
eval(expression[, globals[, locals]])
expression
: 문자열로 된 유효한 파이썬 표현식globals
,locals
: 선택적으로 실행할 스코프(전역/지역 변수) 지정
</> 예시코드:
x = 10
expression = "x * 2 + 5"
result = eval(expression)
print("결과:", result)
🖨️ 출력결과:
결과: 25
🔹 callable(object)
함수
현업에서는 객체가 정말 함수처럼 실행 가능한지 아닌지 헷갈리때가 많습니다. 그래서 콜러블 함수를 활용해 실행 가능한지 확인하는 테스트 코드를 자주 사용합니다.
📖 문법, 구문(syntax):
callable(object)
- 사용자에게 받은 값이 함수일지 아닐지 몰라서.
- 클래스 인스턴스인데 실행하려다가 에러 나는 걸 방지하려고.
- 동적으로 실행할 코드를 미리 확인하고 안전하게 실행하려고.
</> 예시코드: 다양한 객체를 테스트
def my_func():
return "나는 함수입니다."
class MyClass:
def __call__(self):
return "나는 실행 가능한 객체입니다."
g = Greeter()
g() # 사실은 g.__call__()을 의미함 # obj()
class MyEmptyClass:
pass
x = 10 # 숫자
y = "hello" # 문자열
z = [1, 2, 3] # 리스트
obj1 = MyClass() # __call__ 있는 클래스
obj2 = MyEmptyClass() # 아무 메서드 없는 클래스
test_cases = [my_func, MyClass, obj1, obj2, x, y, z]
for i, item in enumerate(test_cases, 1): # (i=index, item=value)
print(f"{i}. {type(item).__name__}: callable? {callable(item)}")
🖨️ 출력결과:
1. function: callable? True
2. type: callable? True
3. MyClass: callable? True
4. MyEmptyClass: callable? False
5. int: callable? False
6. str: callable? False
7. list: callable? False
번호 | 객체 설명 | callable() 결과 |
이유 |
---|---|---|---|
1 | 일반 함수 my_func |
True | 함수는 당연히 실행 가능 |
2 | 클래스 자체MyClass |
True | 클래스는 () 로 인스턴스를 만들 수 있어서 호출 가능 |
3 | __call__() 가진 객체 인스턴스 |
True | 함수처럼 obj() 호출 가능 |
4 | 아무 메서드 없는 객체 | False | 실행할 수 없음 |
5 | 숫자 | False | 실행 대상 아님 |
6 | 문자열 | False | 실행할 수 없음 |
7 | 리스트 | False | 실행할 수 없음 |
🔹 __call__()
이란?
어떤 객체에 ()
괄호를 붙이면 실행되도록 만드는 비밀스런 메서드(함수)예요.
class MyClass:
def __call__(self):
return "나는 실행 가능한 객체입니다."
g = MyClass() # 올바르게 클래스 이름 사용
print(g()) # 사실은 g.__call__()을 실행한 것과 같음
📘 기타 유용한 함수
함수 | 설명 | 예시 |
---|---|---|
input() |
사용자 입력 | input("이름: ") |
print() |
값을 화면에 출력 | print("안녕") |
help() |
도움말 출력 | help(str) |
dir() |
객체의 속성/함수 목록 보기 | dir(list) |
chr() |
숫자를 문자로 변환 | chr(65) → 'A' |
ord() |
문자를 아스키 코드(숫자)로 변환 | ord('A') → 65 |
bin() |
2진수 문자열 반환 | bin(5) → '0b101' |
hex() |
16진수 문자열 반환 | hex(255) → '0xff' |
oct() |
8진수 문자열 반환 | oct(8) → '0o10' |
</> 예시코드: |
print(chr(97)) # 'a'
print(ord('a')) # 97
print(bin(7)) # '0b111'
print(hex(16)) # '0x10'
print(oct(10)) # '0o12'
print(dir(str)) # str 관련 함수 목록 출력
# help(print) # 주석 해제 시 도움말 출력됨
🔹 dir()
함수
어떤 객체가 가지고 있는 속성(변수)이나 메서드(함수)를 리스트로 반환합니다.
쉽게 말해, "무엇을 할 수 있는지" 목록을 보여주는 도구입니다.
</> 예시코드:
word = "hello"
print(dir(word))
🖨️ 출력 결과 (일부 생략):
['__add__', '__class__', '__contains__', ..., 'capitalize', 'count', 'endswith', 'find', 'isalpha', 'isdigit', 'lower', 'upper', 'strip']
🔍해설:
word
는 문자열이니까, dir(word)
는 문자열이 가진 기능(메서드)들을 보여줍니다.
즉, dir(대상)
은 무엇이 가능한지를 보여주는 함수입니다.
✅ Django 모델 객체에 적용
# 예시 모델
from django.db import models
class User(models.Model):
username = models.CharField(max_length=100)
email = models.EmailField()
사용 예시 (views.py나 shell에서)
user = User(username="eunice", email="eunice@example.com")
# 1. 속성 목록 확인
print("모델 속성:", dir(user))
# 2. 속성 존재 여부 확인
if not hasattr(user, "phone"):
print("phone 속성이 정의되어 있지 않음")
# 3. 속성 값 접근
print("이메일:", getattr(user, "email", "이메일 없음"))
# 4. 동적 속성 추가 (일시적)
setattr(user, "nickname", "유니") # DB에는 저장되지 않음
print("닉네임:", getattr(user, "nickname", "없음"))
🔹 chr()
함수
정수(아스키/유니코드 번호)를 해당하는 문자(Character)로 바꿔줍니다.
</> 예시코드: 대문자 A
print(chr(65)) # 아스키 코드 65는 'A'
🖨️ 출력 결과 (일부 생략):
A
</> 예시코드: 한글도 가능 (유니코드 사용)
print(chr(44032)) # 유니코드 44032는 '가'
🖨️ 출력 결과 (일부 생략):
가
</> 예시코드: 반복문과 함께 사용하면 문자표 만들기
for i in range(65, 70): # A(65) ~ E(69)
print(i, "→", chr(i))
🖨️ 출력 결과 (일부 생략):
65 → A
66 → B
67 → C
68 → D
69 → E
💭직접 풀어보세요.
📝 문제1] 아래 3개의 문장을 줄바꿈 없이 하나로 출력해보세요.
["파이썬은", "정말", "재밌어요!"]
🖨️ 출력 결과:
파이썬은 정말 재밌어요!
✅ 정답 코드:
words = ["파이썬은", "정말", "재밌어요!"]
sentence = " ".join(words)
print(sentence)
🔍 해설:
- 공백
" "
을 구분자로 리스트의 문자열을 합침 join()
은 문자열 리스트를 하나의 문장으로 만들 때 유용
📝 문제2] 다음 리스트에서 "콜라"
를 제외한 항목들로만 새 리스트를 만들어 출력해보세요.
‼️ 단, 리스트 내포(list comprehension) 문법을 사용하고, for
반복문과 if
조건을 함께 활용하세요.
drinks = ["물", "주스", "콜라", "커피", "우유"]
✨ 힌트: 리스트 내포 구조:
[리스트들 for 리스트안에 한개의 객체 in 리스트들 if 리스트안에 한개의 객체 != "콜라"]
🖨️ 출력 결과:
['물', '주스', '커피', '우유']
✅ 정답 코드:
drinks = ["물", "주스", "콜라", "커피", "우유"]
filtered = [drink for drink in drinks if drink != "콜라"]
print(filtered)
🔍 해설:
for drink in drinks
: 리스트drinks
에서 음료를 하나씩 꺼냄if drink != "콜라"
: 콜라가 아닌 항목만 선택- → 선택된 항목을
filtered
리스트에 담음
📝 문제4]사용자 조회 수 상위 3명 추출 (이터레이터 + sorted + next) 다음 딕셔너리에서, 조회 수 기준으로 상위 3명의 이름을 순서대로 출력하세요.
views = {
"alice": 120,
"bob": 150,
"carol": 110,
"dave": 300,
"erin": 200
}
🖨️ 출력 결과
dave
erin
bob
✅ 정답 코드:
top3_iter = iter(sorted(views.items(), key=lambda x: x[1], reverse=True))
for _ in range(3):
print(next(top3_iter)[0])
🔍 해설
sorted()
로 값 기준 정렬 →(이름, 조회수)
튜플 목록iter()
로 이터레이터 변환next()
로 순차 접근next()
는 데이터를 순서대로 하나씩 꺼낼 수 있어 메모리 효율적
📝 문제5] 예상 출력 결과는?
</>문제 코드:
cities = ["서울", "부산", "대구"]
for i, city in enumerate(cities):
print(f"{i+1}. {city}")
보기: A:
0. 서울
1. 부산
2. 대구
B:
1. 서울
2. 부산
3. 대구
C:
서울
부산
대구
✅ 정답: B
🖨️ 출력 결과:
1. 서울
2. 부산
3. 대구
🔍 해설:
enumerate(cities)
는i=0
부터 시작- 하지만
print(f"{i+1}. {city}")
로 출력 시+1
을 했기 때문에 1부터 시작하는 번호가 붙어요
📝 문제6] 빈칸 채우기
다음 코드에서 ___
에 들어갈 가장 적절한 코드는?
fruits = ["사과", "배", "포도"]
for idx, fruit in ___:
print(f"{idx}: {fruit}")
보기:
A. range(fruits)
B. enumerate(fruits)
C. list(fruits)
D. fruits.items()
✅ 정답: B. enumerate(fruits)
🖨️ 출력 결과:
0: 사과
1: 배
2: 포도
🔍 해설:
enumerate(fruits)
는 인덱스와 값을 한 번에 꺼내줍니다.range()
는 인덱스만,fruits.items()
는 딕셔너리 전용이라 리스트에서는 사용 불가입니다.list(fruits)
는 값을 꺼내긴 하지만 인덱스를 자동으로 붙여주지 않습니다.
📝 문제7] 인덱스는 0부터 시작한다. 그런데 인덱스를 1부터 시작하게 하려면?
🖨️ 출력 결과:
1. 고양이
2. 강아지
3. 햄스터
✅ 정답코드:
animals = ["고양이", "강아지", "햄스터"]
for idx, animal in enumerate(animals, start=1):
print(f"{idx}. {animal}")
🔍 해설:
enumerate(리스트, start=숫자)
를 사용하면 인덱스를 원하는 숫자부터 시작 가능!- 이 기능은 설문지, 문제 번호 붙일 때 아주 유용합니다.
📝 문제8] 리스트 컴프리헨션으로 짝수 제곱만 구하기
리스트 [1~10]
에서 짝수만 골라 제곱한 리스트를 생성하세요.
🖨️ 출력 결과
[4, 16, 36, 64, 100]
✅ 정답코드:
result = [x**2 for x in range(1, 11) if x % 2 == 0]
print(result)
🔍 해설
for x in range(1, 11)
→ 1~10 순회if x % 2 == 0
→ 짝수만 필터링x**2
→ 제곱 계산
📝 문제9] 짝수의 제곱을 리스트에 담기 다음 코드를 실행하면 어떤 리스트가 출력될까요?
# 짝수의 제곱값을 저장할 빈 리스트 생성
array = []
# 0부터 20 미만까지, 2씩 증가시키며 반복
for i in range(0, 20, 2):
array.append(i * i)
# 리스트 출력
print(array)
❓ 예상되는 출력 결과는?
A. [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
B. [0, 4, 16, 36, 64, 100, 144, 196, 256, 324]
C. [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
D. [0, 4, 16, 36, 64, 100, 144, 196]
✅ 정답: B
🖨️ 정답 출력:
[0, 4, 16, 36, 64, 100, 144, 196, 256, 324]
i 값 |
i * i (제곱값) |
array에 추가된 값 |
---|---|---|
0 | 0 | [0] |
2 | 4 | [0, 4] |
4 | 16 | [0, 4, 16] |
6 | 36 | [0, 4, 16, 36] |
8 | 64 | [0, 4, 16, 36, 64] |
10 | 100 | [0, 4, 16, 36, 64, 100] |
12 | 144 | [0, 4, 16, 36, 64, 100, 144] |
14 | 196 | [0, 4, 16, 36, 64, 100, 144, 196] |
16 | 256 | [0, 4, 16, 36, 64, 100, 144, 196, 256] |
18 | 324 | [0, 4, 16, 36, 64, 100, 144, 196, 256, 324] |
🔍 해설: |
range(0, 20, 2)
는 0부터 18까지 2씩 증가하는 짝수만 반복합니다.i * i
는i
의 제곱값을 의미합니다.- 각 제곱값은
array.append(...)
로 리스트에 하나씩 저장됩니다. - 마지막에
array
를 출력하면 짝수 제곱만 담긴 리스트가 나옵니다.
📝 문제10] 위 코드를 리스트 내포(list comprehension)로 바꾸면?
array = []
for i in range(0, 20, 2):
array.append(i * i)
print(array)
✅ 정답:
array = [i * i for i in range(0, 20, 2)]
📝 문제11] 다음 코드의 출력 결과를 예상하세요
test = (
"이렇게 입력해도 "
"하나의 문자열로 연결되어 "
"생성됩니다."
)
print("test:", test)
❓ 출력 결과는?
A. 줄바꿈되어 출력됨
B. 괄호가 출력됨
C. 문자열이 자동 연결되어 한 줄로 출력됨
D. 문법 오류가 발생함
✅ 정답: C
🖨️ 정답 출력:
test: 이렇게 입력해도 하나의 문자열로 연결되어 생성됩니다.
🔍 해설:
- 파이썬에서는 문자열을 괄호
( )
안에 여러 줄로 나열하면 자동으로 하나의 문자열로 연결됩니다. +
기호 없이도 작동하며, 줄바꿈도 자동 제거됩니다.
📝 문제12] reversed()와 join을 활용한 문자열 뒤집기
문자열 "Python은 강력하다"
를 공백 없이 뒤집어 출력하세요.
🖨️ 정답 결과:
다력강 은nohtyP
✅ 정답 코드:
s = "Python은 강력하다"
print(''.join(reversed(s)))
🔍 해설
reversed(s)
→ 문자열 뒤에서부터 순회하는 이터레이터''.join(...)
→ 문자 하나씩 붙여서 문자열로 재조합
📝 문제13] 다음 중 짝수일 때의 출력 결과는?
number = 6
if number % 2 == 0:
print("\n".join([
"입력한 문자열은 {}입니다.",
"{}는(은) 짝수입니다."
]).format(number, number))
🖨️ 정답 출력:
입력한 문자열은 6입니다.
6는(은) 짝수입니다.
🔍 해설:
join()
은 리스트의 각 문자열을 한 줄로 연결하며 줄바꿈(\n
)으로 붙입니다..format()
은{}
에 각각 값을 채워 넣습니다.format(number, number)
→ 두 개의{}
자리에 같은 숫자 6이 들어감
📝 문제14] generator expression으로 누적합 100 넘는 시점 구하기 1부터 무한히 더하다가 누적합이 100을 처음 넘는 시점의 숫자를 구하세요.
🖨️ 정답 출력:
14 # 수정됨
✅ 정답코드:
gen = (x for x in range(1, 1000))
total = 0
for n in gen:
total += n
if total > 100:
print(n)
break
🔍 해설:
- 제너레이터 표현식은 메모리 절약에 유리
for
반복하면서 누적합 계산break
로 조건 만족 시 즉시 종료
📝 문제15] 아래 코드 실행 시 출력 결과는? (짝수 입력 시)
number = 10
if number % 2 == 0:
print("""\
입력한 문자열은 {}입니다.
{}는(은) 짝수입니다.""".format(number, number))
🖨️ 출력 결과:
입력한 문자열은 10입니다.
10는(은) 짝수입니다.
🔍 해설:
"""\"
← 백슬래시를 붙이면 첫 줄 줄바꿈 없이 바로 출력됩니다.- 여러 줄 문자열을 출력할 때 들여쓰기 없이 자연스럽게 출력 가능
📝 문제16] 사용자 입력값이 홀수인지 짝수인지 판별해, 결과를 아래와 같이 출력하는 프로그램을 리스트와 join()
을 활용하여 작성해보세요.
# 입력예시
정수 입력> 9
# 출력예시
입력한 문자열은 9입니다.
9는(은) 홀수입니다.
✅ 정답 코드:
# 출력예시
number = int(input("정수 입력> "))
if number % 2 == 0:
print("\n".join([
"입력한 문자열은 {}입니다.",
"{}는(은) 짝수입니다."
]).format(number, number))
else:
print("\n".join([
"입력한 문자열은 {}입니다.",
"{}는(은) 홀수입니다."
]).format(number, number))
📝 문제17] dictionary comprehension으로 키 값 바꾸기 다음 딕셔너리에서, 값을 키로, 키를 값으로 뒤집은 새 딕셔너리를 만들어라.
lang = {
"python": 1,
"java": 2,
"c++": 3
}
🖨️ 출력 결과:
{1: 'python', 2: 'java', 3: 'c++'}
✅ 정답 코드
reversed_lang = {v: k for k, v in lang.items()}
print(reversed_lang)
🔍 해설
- 딕셔너리 컴프리헨션은
key: value
쌍을 바꿔 생성 가능 - 키 중복 주의: 값이 중복되면 마지막 값만 남음
📝 문제18] 다음 코드를 실행했을 때 출력 결과로 알맞은 것은?
example_dictionary = {
"키A": "값A",
"키B": "값B",
"키C": "값C",
}
for key, element in example_dictionary.items():
print("dictionary[{}] = {}".format(key, element))
❓ 출력 결과는?
A.
dictionary[값A] = 키A
dictionary[값B] = 키B
dictionary[값C] = 키C
B.
dictionary['key'] = 'value'
dictionary['key'] = 'value'
dictionary['key'] = 'value'
C.
dictionary[키A] = 값A
dictionary[키B] = 값B
dictionary[키C] = 값C
D.
키A:값A
키B:값B
키C:값C
✅ 정답: C
🖨️ 출력 결과:
dictionary[키A] = 값A
dictionary[키B] = 값B
dictionary[키C] = 값C
🔍 해설:
example_dictionary.items()
는 딕셔너리 안의(key, value)
쌍들을 꺼냅니다.- 반복문에서
for key, element in ...:
구문은 각각의 쌍을 한 번에 분해해서 변수에 담는 구조예요. format(key, element)
를 사용하여dictionary[키] = 값
형태로 출력됩니다.
📝 문제19] 빈칸 채우기 문제
다음 코드에서 ___
에 들어갈 가장 적절한 함수는 무엇인가요?
fruit_colors = {
"사과": "빨강",
"바나나": "노랑"
}
for name, color in ___:
print(f"{name}의 색깔은 {color}입니다.")
보기
A. fruit_colors.values()
B. fruit_colors.keys()
C. fruit_colors.items()
D. fruit_colors.list()
✅ 정답: C. fruit_colors.items()
🔍 해설:
items()
는 딕셔너리에서(키, 값)
형태로 꺼낼 수 있도록 해줍니다.values()
나keys()
는 각각 값 또는 키만 꺼내기 때문에 두 변수를 사용할 수 없습니다.
📝 문제20] 다음 코드 실행 시 출력 결과로 알맞은 것은?
numbers = [1, 2, 3, 4, 5, 6]
r_num = reversed(numbers)
print("reversed_numbers:", r_num)
print(next(r_num))
print(next(r_num))
print(next(r_num))
보기: A.
reversed_numbers: [6, 5, 4, 3, 2, 1]
6
5
4
B.
reversed_numbers: <list_reverseiterator object at ...>
6
5
4
C.
reversed_numbers: [1, 2, 3, 4, 5, 6]
1
2
3
D.
reversed_numbers: <reversed_list>
3
4
5
✅ 정답: B
✅ 출력 결과 예시 (메모리 주소는 실행 환경마다 다름)
reversed_numbers: <list_reverseiterator object at 0x7f7d0d69ada0>
6
5
4
🔍 해설
reversed(numbers)
는 역방향으로 값을 꺼낼 수 있는 반복자(iterator)를 반환함next(r_num)
으로 하나씩 값을 꺼낼 수 있음
📝 문제21] enumerate로 라인 넘버 붙여 출력하기 (오타수정됨)
리스트 ["apple", "banana", "cherry"]
에 각 항목 앞에 번호를 붙여 출력하세요.
🖨️ 출력 결과
1. apple
2. banana
3. cherry
✅ 정답 코드
fruits = ["apple", "banana", "cherry"]
for i, fruit in enumerate(fruits, 1):
print(f"{i}. {fruit}")
🔍 해설
enumerate(iterable, start=1)
→ (인덱스, 값) 반환- 반복하면서 순번 매기기 쉽게 가능
📝 문제22] set comprehension으로 공통 문자 추출 (결과 수정됨) 두 문자열에서 공통된 문자만 추출해서 출력하세요.
a = "developer"
b = "explorer"
🖨️ 출력 결과
{'o', 'r', 'e', 'l', 'p'}
✅ 정답 코드
common = {ch for ch in a if ch in b}
print(common)
🔍 해설
set
은 중복 제거ch in b
조건으로 공통 문자만 남김
📝 문제23] 다음 코드 중 실제로 [5, 4, 3, 2, 1]
리스트를 생성하는 코드는?
list_a = [1, 2, 3, 4, 5]
list_reversed = ___
print(list(list_reversed))
보기
A. list_a.reverse()
B. list_a[::-1]
C. reversed(list_a)
D. list(reversed(list_a))
✅ 정답: D
🔍 해설
reversed()
는 반복자(iterator)를 반환하기 때문에list()
로 감싸야 실제 리스트로 보임list_a.reverse()
는 값을 제자리에서 바꿔버리므로 반환값이None
list_a[::-1]
는 슬라이싱으로 리스트를 뒤집지만, 질문 조건은reversed()
함수 기준임
📝 문제24] 숫자 리스트에서 짝수만 문자열로 바꾸기
리스트 [1, 2, 3, 4, 5, 6]
에서 짝수만 골라 문자열 "짝수: 2"
형태로 바꿔 리스트로 만드세요.
🖨️ 출력 결과
['짝수: 2', '짝수: 4', '짝수: 6']
✅ 정답 코드
nums = [1, 2, 3, 4, 5, 6]
result = [f"짝수: {n}" for n in nums if n % 2 == 0]
print(result)
🔍 해설
if n % 2 == 0
: 짝수만 선택f"짝수: {n}"
: 문자열 포맷으로 표현
📝 문제25] next()와 iter()로 리스트 3개만 출력
리스트 [100, 200, 300, 400, 500]
에서 처음 3개만 출력하세요 (반복문 금지).
🖨️ 출력 결과
100
200
300
✅ 정답 코드:
data = [100, 200, 300, 400, 500]
it = iter(data)
print(next(it))
print(next(it))
print(next(it))
🔍 해설
iter()
로 이터레이터 생성next()
를 직접 호출하여 원하는 수만 꺼냄
📝 문제26] 리스트에서 짝수 개수 세기 (comprehension + len)
리스트 [10, 15, 22, 33, 40, 55]
에서 짝수가 몇 개인지 구하세요.
🖨️ 출력 결과
3
✅ 정답 출력:
nums = [10, 15, 22, 33, 40, 55]
count = len([n for n in nums if n % 2 == 0])
print(count)
🔍 해설
- 컴프리헨션으로 조건 만족하는 항목만 리스트화
len()
으로 개수 카운팅
📝 문제27] 다음 기존 코드를 리스트 내포 방식으로 바꾸면 어떤 코드가 될까요?
array = []
for i in range(0, 20, 2):
array.append(i * i)
❓ 보기
A. [i for i in range(0, 20, 2)]
B. [i * 2 for i in range(0, 20, 2)]
C. [i * i for i in range(0, 20, 2)]
D. [i ** 2 if i % 2 == 0 for i in range(20)]
✅ 정답: C
🖨️ 출력 결과:
[0, 4, 16, 36, 64, 100, 144, 196, 256, 324]
🔍 해설:
range(0, 20, 2)
는 0부터 19까지 2씩 증가 → 짝수만 순회i * i
는 각 숫자의 제곱값
📝 문제28] 다음 리스트 내포의 출력 결과는?
result = [x for x in range(10) if x % 2 == 0]
print(result)
보기:
A. [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
B. [1, 3, 5, 7, 9]
C. [0, 2, 4, 6, 8]
D. [2, 4, 6, 8, 10]
✅ 정답: C
🔍 해설:
range(10)
→ 0부터 9까지 숫자if x % 2 == 0
→ 짝수만 조건 통과- 결과는
[0, 2, 4, 6, 8]
📝 문제29] 사용자에게 이름을 3번 입력받아 리스트에 저장하세요. 그리고 각 이름 앞에 번호를 붙여서 출력하세요.
🖨️ 출력 예시 (입력: 영희, 민수, 정우):
1. 영희
2. 민수
3. 정우
✅ 정답 코드:
names = []
for i in range(3):
name = input(f"{i+1}번째 이름 입력: ")
names.append(name)
for idx, name in enumerate(names, start=1):
print(f"{idx}. {name}")
🔍 해설:
enumerate(..., start=1)
을 사용하면 번호 + 항목을 동시에 가져올 수 있음
📝 문제30] 다음 3행 2열의 리스트에서 각 요소의 행/열 위치와 값을 출력하고,
값이 50 이상이면 '🔥 주목' 이라는 표시를 함께 출력하세요.
nums = [
[10, 20],
[30, 40],
[50, 60]
]
🌟 힌트:
enumerate()
를 사용해 행/열의 인덱스를 함께 가져옵니다.- 조건에 따라 특정 값에만 강조 마크(🔥)를 붙입니다.
🖨️ 출력 결과:
0행 0열 → 10
0행 1열 → 20
1행 0열 → 30
1행 1열 → 40
2행 0열 → 50 🔥 주목
2행 1열 → 60 🔥 주목
✅ 정답 코드:
nums = [
[10, 20],
[30, 40],
[50, 60]
]
for i, row in enumerate(nums):
for j, value in enumerate(row):
if value >= 50:
mark = "🔥 주목"
else:
mark = ""
print(f"{i}행 {j}열 → {value} {mark}")
✅ 정답 코드: 삼항조건식으로 표현
for i, row in enumerate(nums):
for j, value in enumerate(row):
mark = "🔥 주목" if value >= 50 else ""
print(f"{i}행 {j}열 → {value} {mark}")